<?php
/**
 * Dblib抽象层
 * @package Dblib
 * @author Chengxuan <chengxuan@leju.sina.com.cn>
 * @version #Id:abstract.php 2010-4-22 下午02:31:35#
 */
abstract class Dblib_Abstract
{
	/**
	 * 表名
	 * @var string
	 */
	protected $table='';
	
	/**
	 * 数据库操作对象
	 * @var Cls_Db_Base
	 */
	protected $db=null;
	
	/**
	 * 异常错误对象
	 * @var mixed
	 */
	public $exception = null;
	
	/**
	 * 构造方法
	 */
	public function __construct($exception=null)
	{
		$this->db = Cls_Db::D();
		$this->table = Cls_Db::PRE . strtolower(substr(get_class($this), 6));
		$this->changeException($exception);
		
		$this->_after_new();
	}
	
	/**
	 * 实例化之后的方法，作用于继承后的构造方法
	 */
	protected function _after_new(){}
	
	/**
	 * 切换异常操作对象
	 * @param Exception $exception
	 * @return Dblib_Abstract
	 */
	public function changeException($exception)
	{
		if (class_exists($exception)) $this->exception = $exception;
		return $this;
	}
	
	/**
	 * 插入数据
	 * @param array		$data	要插入的数据Array($k1=>$v1, $k2=>$v2)
	 * @param boolean	$ignore	是否采用忽略插入
	 * @return int				成功返回插入产生的ID，失败返回false
	 */
	public function insert($data, $ignore=false)
	{
		$type = !$ignore ? Cls_Db_Base::TYPE_INSERT : Cls_Db_Base::TYPE_INSERT_IGNORE; 
		$result = $this->db->autoExecute($type, $this->table, $data);
		return $result ? (int)$this->db->lastId() : $result;;
	}
	
	/**
	 * 更新数据
	 * @param array		$data	要更新的数据Array($k1=>$v1, $k2=>$v2)
	 * @param string	$where	更新条件
	 * @param string	$param	条件参数
	 * @param string	$limit	限制更新多少条数据
	 * @return mixed	成功返回更新了多少条数据，失败返回false
	 */
	public function update($data, $where='', $param='', $limit=null)
	{		
		return $this->db->autoExecute(Cls_Db_Base::TYPE_UPDATE, $this->table, $data, $where, $param, $limit);
	}
	
	/**
	 * 替换插入数据
	 * @param	array	$data	要替换的数据Array($k1=>$v1, $k2=>$v2)
	 * @return	int				成功返回插入产生的ID，失败返回false
	 */
	public function replace($data)
	{
		$result = $this->db->autoExecute(Cls_Db_Base::TYPE_REPLACE, $this->table, $data);
		return $result ? $this->db->lastId() : $result;;
	}
	
	/**
	 * 删除数据
	 * @param mixed		$where	条件（直接写ID，或一组ID[array]，或SQL语句）
	 * @param array		$param	写SQL时传入的变量
	 * @param string	$limit	限制删除多少条数据
	 * @return int				成功返回删除了多少条数据，失败返回false
	 */
	public function delete($where, $param=null, $limit=null)
	{
		//预处理数据
		if(is_string($where))
		{
			$where = 'WHERE ' . trim($where);
		}
		
		//纯数字，当作ID处理
		if(Cls_Validator::is_num($where))
		{
			$param = array($where);
			$where = "WHERE id = ?";
		}
		
		//数组，当作一群ID处理
		elseif (is_array($where))
		{
			$param = array($where);
			$where = "WHERE id IN (?)";
		}
		
		$sql = "DELETE FROM {$this->table} {$where}";
		
		if($limit)
		{
			if(!Cls_Validator::limit($limit))
			{
				return false;
			}
			
			$sql .= " LIMIT {$limit}";
		}
		
		return $this->db->execute($sql, $param, true);
	}
	
	/**
	 * 抛出错误（根据设置抛出异常或返回错误对象）
	 * @param unknown_type $message
	 * @param unknown_type $code
	 */
	protected function error($message, $code=0)
	{
		if($this->exception)
		{
			throw new $this->exception($message, $code);
		}
		return new Cls_Error($message, $code);
	}
	
	/**
	 * 检查数据的合法性
	 * @param array		$rule	规则
	 * @param array		$data	数据内容（Hashmap）
	 * @return stdClass			{success:boolean, message:string, code:int}
	 */
	static function checkData(array $rule, array $data)
	{
		$result = new stdClass;
		
		try {

			$error = array();
			foreach($rule as $field => $value)
			{
				foreach($value as $func=>$val)
				{
					$params = array($data[$field]);
					if(is_array($val))
					{
						if(!is_array($val[0]))
						{
							throw new Exception('Rule格式错误', 401);
						}
						$params = array_merge($params, $val[0]);
						$msg = $val[1];
					}
					else
					{
						$msg = $val;
					}
					
					if(!call_user_func_array(array('Cls_Validator', $func), $params))
					{
						$error[] = $msg;
					}
				}
			}
			
			if($error)
			{
				throw new Exception(implode(';', $error), 500);
			}
			
			$result->success = true;
		}
		catch(Exception $e)
		{
			$result->success = false;
			$result->message = $e->getMessage();
			$result->code = $e->getCode();
		}
		
		return $result;
	}
}